package com.breaktian.assemble.router;

import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.annotation.RequiresApi;
import android.text.TextUtils;
import android.util.Size;
import android.util.SizeF;

import com.breaktian.assemble.utils.LogUtil;
import com.breaktian.assemble.router.i.IRouterInterceptor;
import com.breaktian.assemble.router.i.IRouterResultCallback;
import com.breaktian.assemble.router.parse.Rule;

import java.io.Serializable;
import java.util.List;


/**
 * Created by keke.tian on 2017/7/26.
 *
 * 跳转者
 * 最后都要调用commit
 *
 *
 *
 */

abstract class AbsRouter {

    private static final String WEB_URL ="web_url" ;
    private Context mContext;
    private Activity mActivity;
    private Bundle mBundle;
    private int mFlags = -1;
    private IRouterInterceptor mInterceptor;
    private IRouterResultCallback mResultCallback;
    private String mWebViewSchema;

    private String tag = "router ";


    abstract List<String> getSchemaPrefixList();
    abstract VpRouter getInstance();
    abstract String getDefaultWebviewSchema();


    public VpRouter context(Context context){
        this.mContext = context;
        return getInstance();
    }

    public VpRouter fragment(Fragment fragment){
        this.mActivity = fragment.getActivity();
        return getInstance();
    }

    public VpRouter activity(Activity activity){
        this.mActivity = activity;
        return getInstance();
    }

    public VpRouter flags(int flags){
        this.mFlags = flags;
        return getInstance();
    }

    /**
     * 指定webview的schema
     * */
    public VpRouter webView(String webviewSchema){
        this.mWebViewSchema = webviewSchema;
        return getInstance();
    }

    /**
     * 最终跳转方法
     * */
    public void jump(Object target){
        jump(target,-1);
        commit();
    }

    /**
     * @param requestCode >=0
     * */
    public void jumpForResult(Object target, int requestCode){
        if(requestCode<0){
            LogUtil.i(tag+"invalid requestCode,requestCode must >=0");
            //设置回调
            onError(RouterError.ERROR_CODE_JUMPFORRESULT_REQUEST_CODE_INVALID);
        }
        if(mActivity==null){
            LogUtil.i(tag+"startActivityForResult need Activity context , please setActivity or setFragment before");
            onError(RouterError.ERROR_CODE_NOT_SET_ACTIVITY);
        }
        jump(target,requestCode);
        commit();
    }

    /**
     * 设置拦截器
     * */
    public VpRouter setInterceptor(IRouterInterceptor interceptor){
        this.mInterceptor = interceptor;
        return getInstance();
    }

    /**
     * 设置结果回调
     * */
    public VpRouter setResultCallback(IRouterResultCallback resultCallback){
        this.mResultCallback = resultCallback;
        return getInstance();
    }

    /**
     * 支持url、schema、intent启动
     * startAcvivityFrorResult要求 requestCode>=0
     * */
    void jump(Object target,int requestCode){
        if(target==null){
            LogUtil.i(tag+"target is null");
            onError(RouterError.ERROR_CODE_JUMP_TARGET_IS_NULL_OR_EMPTY);
            return;
        }
        if(target instanceof Intent){
            LogUtil.i(tag+"target is Intent");
            startForResultWithIntent((Intent) target,requestCode);
        }else if(target instanceof String){
            String s = (String)target;
            LogUtil.i(tag+"target : "+s);
            if(TextUtils.isEmpty(s)){
                LogUtil.i(tag+"target is empty");
                onError(RouterError.ERROR_CODE_JUMP_TARGET_IS_NULL_OR_EMPTY);
                return;
            }
            if(isConfigedSchemaPrefix(s)){
                parseUrlParams2Bundle(s);
                startWithSchema(filterSchema(s),requestCode);
            }else if(s.startsWith("http:")||s.startsWith("https:")){
                parseUrlParams2Bundle(s);
                startWithHttp(s,requestCode);
            }else{
                LogUtil.i(tag+"invalid url or schema:"+s);
                onError(RouterError.ERROR_CODE_INVALID_URL_OR_SCHEMA);
            }
        }
    }

    boolean isConfigedSchemaPrefix(String s){
        if(getSchemaPrefixList()!=null&&getSchemaPrefixList().size()>0){
            for (String prefix:getSchemaPrefixList()){
                if(s.startsWith(prefix)){
                    return true;
                }
            }
        }
        return false;
    }

    void startWithSchema(String schema,int requestCode){
        Rule rule = RouterTable.get().getRule(schema);
        if(rule!=null){
            Class mClass = reflectClazz(rule.getClazz());
            if(mClass!=null){
                LogUtil.i(tag+"通过反射启动intent("+rule.getClazz()+")");
                startWithReflect(mClass,requestCode,null);
            }else{
                LogUtil.i(tag+"反射获取class失败 "+rule.getClazz());
                LogUtil.i(tag+"通过隐式意图启动intent");
                startWithAction(rule.getAction(),requestCode,null);
            }

        }else{
            LogUtil.i(tag+"startWithSchema, rule is null");
            onError(RouterError.ERROR_CODE_SCHEMA_RULE_IS_NULL);
        }
    }

    /**
     * url启动webview
     *
     * */
    void startWithHttp(String url,int requestCode){
        if(!TextUtils.isEmpty(url)){

            String webviewSchema;
            //判断有没有设置指定的webviewSchema
            if(TextUtils.isEmpty(mWebViewSchema)){//没有设置（没有调用setWebViewSchema方法）
                webviewSchema = getDefaultWebviewSchema();
            }else{//指定了webviewSchema
                webviewSchema = mWebViewSchema;
            }
            if(TextUtils.isEmpty(webviewSchema)){
                LogUtil.i(tag+"webviewSchema is empty");
                onError(RouterError.ERROR_CODE_WEBVIEW_SCHEMA_NOT_SET);
                return;
            }
            Rule rule = RouterTable.get().getRule(webviewSchema);
            if(rule!=null){
                Class mClass = reflectClazz(rule.getClazz());
                if(mClass!=null){
                    LogUtil.i(tag+"通过反射启动intent("+rule.getClazz()+")");
                    LogUtil.i(tag+"通过反射启动intent");
                    startWithReflect(mClass,requestCode,url);
                }else{
                    LogUtil.i(tag+"反射获取class失败 "+rule.getClazz());
                    LogUtil.i(tag+"通过隐式意图启动intent");
                    startWithAction(rule.getAction(),requestCode,url);
                }

            }else{
                LogUtil.i(tag+"startWithHttp rule is null");
                onError(RouterError.ERROR_CODE_WEBVIEW_RULE_IS_NULL);
            }

        }else{
            LogUtil.i(tag+"startWithHttp url is empty");
            onError(RouterError.ERROR_CODE_WEBVIEW_URL_IS_EMPTY);
        }

    }

//    /**
//     * 通过Component启动
//     * */
//    void startWithComponent(String clazz, int requestCode,String webUrl){
//        String pkg = null;
//        try{
//            pkg = clazz.substring(0,clazz.lastIndexOf("."));
//        }catch (Exception e){
//            e.printStackTrace();
//            onError(RouterError.ERROR_CODE_PACKAGE_INVALID);
//        }
//        if(TextUtils.isEmpty(pkg)){
//            onError(RouterError.ERROR_CODE_PACKAGE_INVALID);
//        }
//        Intent intent = new Intent();
//        ComponentName componentName = new ComponentName(pkg, clazz);
//        intent.setComponent(componentName);
//
//        if(!TextUtils.isEmpty(webUrl)){
//            intent.putExtra("web_url",webUrl);
//        }
//
//        startForResultWithIntent(intent,requestCode);
//    }

    /**
     * 通过反射启动组件
     *
     * */
    void startWithReflect(Class clazz, int requestCode,String webUrl){
        Intent intent = null;
        if(mContext!=null){
            intent = new Intent(mContext,clazz);
        }else if(mActivity!=null){
            intent = new Intent(mActivity,clazz);
        }
        if(intent==null){
            LogUtil.i(tag+"intent is null, invalid package Context!");
            onError(RouterError.ERROR_CODE_INVALID_PACKAGE_CONTEXT);
            return;
        }

        if(!TextUtils.isEmpty(webUrl)){
            intent.putExtra(WEB_URL,webUrl);
        }

        startForResultWithIntent(intent,requestCode);


    }

    /**
     * 通过隐式意图启动组件
     *
     * */
    void startWithAction(String action, int requestCode,String webUrl){
        if(!TextUtils.isEmpty(action)){
            Intent intent = new Intent();
            intent.setAction(action);
            if(!TextUtils.isEmpty(webUrl)){
                intent.putExtra(WEB_URL,webUrl);
            }
            startForResultWithIntent(intent,requestCode);
        }else{
            LogUtil.i(tag+"startWithSchema intentAction is empty");
            onError(RouterError.ERROR_CODE_INTENTACTION_IS_EMPTY);
        }

    }

    void startForResultWithIntent(Intent intent,int requestCode){
        //拦截器
        if(mInterceptor!=null){
            //是否取消跳转
            boolean isCancel = mInterceptor.cancel();
            if(isCancel){
                LogUtil.i(tag+"interceptor canceled this jump");
                onError(RouterError.ERROR_CODE_JUMP_CANCELED_BY_INTERCEPTOR);
                return;
            }
            //添加参数
            Bundle bundle = mInterceptor.addExtras();
            if(bundle!=null){
                if(mBundle!=null){
                    mBundle.putAll(bundle);
                }else{
                    mBundle = bundle;
                }
            }
        }
        if(requestCode==-1){
            if(mActivity!=null){
                if(mBundle!=null){
                    intent.putExtras(mBundle);
                }
                if(mFlags!=-1){
                    intent.setFlags(mFlags);
                }
                mActivity.startActivity(intent);
                if(mResultCallback!=null) mResultCallback.onSuccess();
            }else if(mContext!=null){
                if(mBundle!=null){
                    intent.putExtras(mBundle);
                }
                if(mFlags!=-1){
                    intent.setFlags(mFlags);
                }
                mContext.startActivity(intent);
                if(mResultCallback!=null) mResultCallback.onSuccess();
            }else{
                LogUtil.i(tag+"startActivity fail , mActivity or mContext is null");
                onError(RouterError.ERROR_CODE_NOT_SET_ACTIVITY_OR_CONTEXT);
            }
        }else{
            if(mActivity!=null){
                if(mBundle!=null){
                    intent.putExtras(mBundle);
                }
                if(mFlags!=-1){
                    intent.setFlags(mFlags);
                }
                mActivity.startActivityForResult(intent,requestCode);
                if(mResultCallback!=null) mResultCallback.onSuccess();
            }else {
                LogUtil.i(tag+"startActivityForResult fail , mActivity is null");
                onError(RouterError.ERROR_CODE_NOT_SET_ACTIVITY);
            }
        }
    }

    /**
     * 一定要调用此方法
     * 不然可能会导致内存泄漏
     * */
    void commit(){
        if(mBundle!=null){
            mBundle.clear();
            mBundle = null;
        }
        if(mContext!=null){
            mContext = null;
        }
        if(mActivity!=null){
            mActivity = null;
        }
        if(mInterceptor!=null){
            mInterceptor = null;
        }
        if(mResultCallback!=null){
            mResultCallback = null;
        }
        if(mWebViewSchema!=null){
            mWebViewSchema = null;
        }
        mFlags  =-1;
    }

    /**
     * 添加参数
     * */
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public VpRouter extra(String key, Object value){
        if(mBundle==null){
            mBundle = new Bundle();
        }
        if(value instanceof String){
            mBundle.putString(key, (String) value);
        }else if(value instanceof String[]){
            mBundle.putStringArray(key, (String[]) value);
        }else if(value instanceof Byte){
            mBundle.putByte(key, (Byte) value);
        }else if(value instanceof byte[]){
            mBundle.putByteArray(key, (byte[]) value);
        }else if(value instanceof Short){
            mBundle.putShort(key, (Short) value);
        }else if(value instanceof short[]){
            mBundle.putShortArray(key, (short[]) value);
        }else if(value instanceof Character){
            mBundle.putChar(key, (Character) value);
        }else if(value instanceof char[]){
            mBundle.putCharArray(key, (char[]) value);
        }else if(value instanceof Boolean){
            mBundle.putBoolean(key, (Boolean) value);
        }else if(value instanceof boolean[]){
            mBundle.putBooleanArray(key, (boolean[]) value);
        }else if(value instanceof Double){
            mBundle.putDouble(key, (Double) value);
        }else if(value instanceof double[]){
            mBundle.putDoubleArray(key, (double[]) value);
        }else if(value instanceof Float){
            mBundle.putFloat(key, (Float) value);
        }else if(value instanceof Float){
            mBundle.putFloatArray(key, (float[]) value);
        }else if(value instanceof Integer){
            mBundle.putInt(key, (Integer) value);
        }else if(value instanceof int[]){
            mBundle.putIntArray(key, (int[]) value);
        }else if(value instanceof Serializable){
            mBundle.putSerializable(key, (Serializable) value);
        }else if(value instanceof Parcelable){
            mBundle.putParcelable(key, (Parcelable) value);
        }else if(value instanceof Parcelable[]){
            mBundle.putParcelableArray(key, (Parcelable[]) value);
        }else if(value instanceof Size){
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                mBundle.putSize(key, (Size) value);
            }
        }else if(value instanceof SizeF){
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                mBundle.putSizeF(key, (SizeF) value);
            }
        }

        return getInstance();
    }


    /**
     * 解析url参数
     * http://www.baidu.com?a=100&b=222
     * demo://innerapp.testsecurity?title=个人中心&type=21
     * */
    void parseUrlParams2Bundle(String s) {
        if(s!=null){
            s = s.trim().toLowerCase();
            int index = s.indexOf("?");
            if(index>-1){
                String paramString = s.substring(index + 1);
                String[] keyValues = paramString.split("&");
                if(keyValues.length>0){
                    if(mBundle==null){
                        mBundle = new Bundle();
                    }
                    for (String str : keyValues) {
                        String[] param = str.split("=");
                        if(param.length==2){
                            String key = param[0];
                            String value = param[1];
                            mBundle.putString(key,value);
                        }else{
                            onError(RouterError.ERROR_CODE_URL_PARAMS_INVALID);
                        }
                    }
                }
            }

        }
    }

    /**
     * 将schema的参数过滤掉
     * */
    String filterSchema(String schema){
        int index = schema.indexOf("?");
        if(index>-1){
            schema = schema.substring(0,index);
        }
        return schema;
    }


    public Class reflectClazz(String className) {
        Class<?> aClass = null;
        if(TextUtils.isEmpty(className)){
            return aClass;
        }
        try {
            aClass = Class.forName(className);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            LogUtil.i(tag+"reflectClazz ClassNotFoundException");
        }
        return aClass;
    }



    void onError(int code){
        if(mResultCallback!=null)
            mResultCallback.onFail(RouterError.get(code));
    }





}
